package com.deploy.service;

import com.deploy.model.ServerInfo;
import com.deploy.util.SCPUtil;
import com.deploy.util.SSHUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;

/**
 * 部署服务类
 * 负责将应用程序部署到远程服务器
 */
@Slf4j
public class DeploymentService {

    public DeploymentService() {}
    
    /**
     * 部署应用到多个服务器
     *
     * @param serverList 服务器列表
     * @return 部署成功的服务器数量
     */
    public int deployToServers(List<ServerInfo> serverList) {
        log.info("开始部署应用到{}个服务器", serverList.size());
        int successCount = 0;

        // 循环处理每个服务器
        for (ServerInfo server : serverList) {
            log.info("开始部署到服务器: {}", server.getIp());

            Session session = null;
            try {
                // 创建SSH连接
                session = SSHUtil.createSession(server);

                // 检测操作系统类型
                if (server.getOsType() == ServerInfo.OsType.LINUX) {
                    // 确认操作系统类型
                    ServerInfo.OsType detectedOsType = SSHUtil.detectOsType(session);
                    server.setOsType(detectedOsType);
                }

                log.info("服务器操作系统类型: {}", server.getOsType());

                // 获取格式化的部署路径
                String deployPath = server.getFormattedDeployPath();

                // 构建远程文件路径
                String remoteAgentPath;
                String remoteConfigPath;

                if (server.getOsType() == ServerInfo.OsType.WINDOWS) {
                    remoteAgentPath = deployPath + "agent.exe";
                    remoteConfigPath = deployPath + "application.yaml";

                    // 新增：停止Windows程序
                    String stopCmd = "taskkill /f /im agent.exe >nul 2>&1";
                    SSHUtil.executeCommand(session, stopCmd);
                } else {
                    remoteAgentPath = deployPath + "agentLinux";
                    remoteConfigPath = deployPath + "application.yaml";

                    // 新增：停止Linux程序
                    String stopCmd = "if [ -f " + deployPath + "agent.pid ]; then " +
                            "pid=$(cat " + deployPath + "agent.pid); " +
                            "if ps -p $pid > /dev/null; then kill $pid; fi; " +
                            "fi";
                    SSHUtil.executeCommand(session, stopCmd);
                }

                // 传输文件
                boolean agentTransferred = SCPUtil.transferFile(session, server.getCurrentAgentFilePath(), remoteAgentPath);
                boolean configTransferred = SCPUtil.transferFile(session, server.getCurrentConfigFilePath(), remoteConfigPath);

                if (!agentTransferred || !configTransferred) {
                    log.error("文件传输失败: {}", server.getIp());
                    continue;
                }

                // 根据操作系统类型执行不同的部署操作
                if (server.getOsType() == ServerInfo.OsType.WINDOWS) {
                    deployToWindowsServer(session, server, deployPath, remoteAgentPath);
                } else {
                    deployToLinuxServer(session, server, deployPath, remoteAgentPath);
                }

                successCount++;

            } catch (JSchException | IOException e) {
                log.error("部署到服务器{}失败: {}", server.getIp(), e.getMessage(), e);
            } finally {
                SSHUtil.closeSession(session);
            }
        }

        log.info("部署完成，成功: {}/{}个服务器", successCount, serverList.size());
        return successCount;
    }

    /**
     * 部署到Linux服务器
     *
     * @param session         SSH会话
     * @param server          服务器信息
     * @param deployPath      部署路径
     * @param remoteAgentPath 远程Agent路径
     * @throws JSchException 如果SSH操作失败
     * @throws IOException   如果IO操作失败
     */
    private void deployToLinuxServer(Session session, ServerInfo server, String deployPath, String remoteAgentPath)
            throws JSchException, IOException {
        log.info("执行Linux部署操作");

        // 设置执行权限
        String chmodCommand = "chmod +x " + remoteAgentPath;
        SSHUtil.executeCommand(session, chmodCommand);

        // 创建启动脚本
        String startScriptPath = deployPath + "start_agent.sh";
        String startScriptContent = "#!/bin/bash\n" +
                "cd " + deployPath + "\n" +
                "nohup ./agentLinux > agent.log 2>&1 &\n" +
                "echo $! > agent.pid\n" +
                "echo \"Agent started with PID $(cat agent.pid)\"";

        // 写入启动脚本
        String createScriptCommand = "cat > " + startScriptPath + " << 'EOL'\n" +
                startScriptContent + "\nEOL";
        SSHUtil.executeCommand(session, createScriptCommand);

        // 设置脚本执行权限
        String chmodScriptCommand = "chmod +x " + startScriptPath;
        SSHUtil.executeCommand(session, chmodScriptCommand);

        // 停止旧进程（如果存在）
        String stopCommand = "if [ -f " + deployPath + "agent.pid ]; then " +
                "pid=$(cat " + deployPath + "agent.pid); " +
                "if ps -p $pid > /dev/null; then kill $pid; fi; " +
                "fi";
        SSHUtil.executeCommand(session, stopCommand);

        // 启动应用
        String startCommand = startScriptPath;
        String result = SSHUtil.executeCommand(session, startCommand);

        log.info("Linux部署结果: {}", result);
    }

    /**
     * 部署到Windows服务器
     *
     * @param session         SSH会话
     * @param server          服务器信息
     * @param deployPath      部署路径
     * @param remoteAgentPath 远程Agent路径
     * @throws JSchException 如果SSH操作失败
     * @throws IOException   如果IO操作失败
     */
    private void deployToWindowsServer(Session session, ServerInfo server, String deployPath, String remoteAgentPath)
            throws JSchException, IOException {


        // 1. 创建启动脚本
        String startBatPath = deployPath + "start_agent.bat";
        String startBatContent = "@echo off\r\n" +
                "cd /d \"" + deployPath + "\"\r\n" +
                "taskkill /f /im agent.exe >nul 2>&1\r\n" +
                "start \"\" /min agent.exe > agent.log 2>&1\r\n" +
                "timeout /t 3 >nul\r\n" +
                "for /f \"tokens=2\" %%i in ('tasklist /fi \"imagename eq agent.exe\" /nh') do echo %%i > agent.pid\r\n";

        // 2. 创建计划任务脚本
        String taskName = "AgentService_" + server.getIp().replace(".", "_");
        String createTaskCmd = "schtasks /create /tn \"" + taskName + "\" " +
                "/tr \\\"" + startBatPath + "\\\" /sc onstart /ru SYSTEM /f";
        String runTaskCmd = "schtasks /run /tn \"" + taskName + "\"";
        String deleteTaskCmd = "schtasks /delete /tn \"" + taskName + "\" /f";

        // 3. 写入启动脚本
        String[] batLines = startBatContent.split("\r\n");
        for (String line : batLines) {
            SSHUtil.executeCommand(session, "echo " + line + " >> \"" + startBatPath + "\"");
        }

        // 4. 删除可能存在的旧任务
        SSHUtil.executeCommand(session, deleteTaskCmd);

        // 5. 创建并运行计划任务
        String createResult = SSHUtil.executeCommand(session, createTaskCmd);
        log.info("创建计划任务结果: {}", createResult);

        String runResult = SSHUtil.executeCommand(session, runTaskCmd);
        log.info("运行计划任务结果: {}", runResult);

        // 6. 验证进程是否运行
        String verifyCmd = "tasklist /fi \"imagename eq agent.exe\"";
        String verifyResult = SSHUtil.executeCommand(session, verifyCmd);

        if (verifyResult.contains("agent.exe")) {
            log.info("验证成功: agent.exe 正在运行");
        } else {
            log.error("验证失败: agent.exe 未运行");
            // 检查日志文件内容
            String logContent = SSHUtil.executeCommand(session, "type \"" + deployPath + "agent.log\"");
            log.error("agent.log 内容: {}", logContent);
        }
    }
}
